package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {


    @Autowired
    private CourseMarketService courseMarketService;

    /**
     * 查询课程信息
     */
    @Override
    public PageVO queryCurseListByPage(PageRequestParams pagePrarms, QueryCourseModel model, Long companyId) {
        //1.构建查询条件:使用LambdaQuery
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();

        //判断审核状态
        // queryWrapper.eq(!(StringUtil.isBlank(model.getAuditStatus())), CourseBase::getAuditStatus, model.getAuditStatus());
        if (!(StringUtil.isBlank(model.getAuditStatus()))) {
            queryWrapper.eq(CourseBase::getAuditStatus, model.getAuditStatus());
        }
        //判断课程名称
        //queryWrapper.eq(!(StringUtil.isBlank(model.getCourseName())), CourseBase::getName, model.getCourseName());
        if (!(StringUtil.isBlank(model.getCourseName()))) {
            queryWrapper.like(CourseBase::getName, model.getCourseName());
        }

        //判断令牌
        queryWrapper.eq(!(ObjectUtils.isEmpty(companyId)),CourseBase::getCompanyId, companyId);

        //2.构建分页
        if (pagePrarms.getPageNo() < 0 || pagePrarms.getPageSize() < 0) {
            return null;
        }
        Page<CourseBase> basePage = new Page<>(pagePrarms.getPageNo(), pagePrarms.getPageSize());

        //3.查询数据库返回数据
        Page<CourseBase> result = this.page(basePage, queryWrapper);
        List<CourseBase> courseBaseList = result.getRecords();

        //4.对查询数据进行封装，返回给controller
        if (CollectionUtils.isEmpty(courseBaseList)) {
            return null;
        }

        //把courseBaseList封装为courseBaseDTOList
        List<CourseBaseDTO> courseBaseDTOList = CourseConvert.INSTANCE.entitys2DTOs(courseBaseList);
        //创建返回对象
        PageVO pageVO = new PageVO(courseBaseDTOList, result.getTotal(), pagePrarms.getPageNo(), pagePrarms.getPageSize());

        return pageVO;
    }

    /**
     * 添加课程分析：
     * 1.是否开启事务
     * 2.对参数的关键数据进行判断
     * 3.添加数据
     * 4.对返回结果进行封装
     */
    @Override
    @Transactional //1增删改都要加事务
    public CourseBaseDTO insertCourseBase(CourseBaseDTO courseDto) {
        //2.对关键参数进行判断
        verifyCourseMsg(courseDto);
        //3.添加数据
        //3.1 把DTO--->>PO
        CourseBase courseBase = CourseConvert.INSTANCE.DTO2entity(courseDto);

        //3.2添加审核状态
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        //3.2添加是否删除,数据可默认为使用状态。无需添加
        // courseBase.setStatus(CommonEnum.USING_FLAG.getCodeInt());
        boolean save = this.save(courseBase);
        if (!save) {
            //插入失败 抛异常
            throw new RuntimeException("添加课程失败");
        }

        //4.添加market数据,向market数据库中添加数据
        CourseMarket market = new CourseMarket();
        //如果是收费的才添加price数据
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(courseDto.getCharge())) {
            float floatValue = courseDto.getPrice().floatValue();
            market.setPrice(floatValue);
        }
        market.setCharge(courseDto.getCharge());
        market.setCourseId(courseBase.getId());

        boolean save1 = courseMarketService.save(market);
        if (!save1) {
            throw new RuntimeException("添加课程失败");
        }

        //保存成功，直接返回dto
        return courseDto;
    }

    /**
     * 根据id查询课程信息,机构只能查询自己的课程，所有必须传入机构id
     * 1.判断关键性参数
     * 2.查询数据库
     * 3.判断课程是否是删除状态
     * 4.查询营销数据，判断是否存在
     * 5.封装返回结果
     */
    @Override
    public CourseBaseDTO queryByCourseID(Long courseBaseId, Long companyId) {
        //1.判断关键参数，只要有一个为空就报错
        if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)) {
            throw new RuntimeException("关键参数缺失");
        }
        //2.查询数据库
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, courseBaseId);
        queryWrapper.eq(CourseBase::getCompanyId, companyId);

        CourseBase courseBase = this.getOne(queryWrapper);
        //3.判断是否已经删除
        if (ObjectUtils.isEmpty(courseBase) ||
                CommonEnum.DELETE_FLAG.getCodeInt().equals(courseBase.getStatus())) {
            throw new RuntimeException("课程不存在或已被删除");
        }

        //4.查询营销数据，
        LambdaQueryWrapper<CourseMarket> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseMarket::getCourseId, courseBase.getId());
        CourseMarket courseMarket = courseMarketService.getOne(wrapper);
        //4.1判断营销数据是否存在
        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("营销数据不存在");
        }

        //5.封装返回结果
        CourseBaseDTO courseBaseDTO = CourseConvert.INSTANCE.entity2DTO(courseBase);

        //5.1添加营销数据
        if (!(ObjectUtils.isEmpty(courseMarket.getPrice()))) {
            //收费的课程才添加价格数据
            courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice()));
        }

        courseBaseDTO.setCharge(courseMarket.getCharge());


        return courseBaseDTO;
    }

    /*
        修改课程数据分析
        1.添加事务
        2.判断关键参数
        3.根据课程id查询课程是否存在
        4.判断课程状态，只有未提交或者审核未通过的才能修改
        5.判读是否是同一家机构
        6.修改数据，
        7.封装数据进行返回
     */
    @Override
    @Transactional //1.添加事务
    public CourseBaseDTO updateCourseBase(CourseBaseDTO courseDto) {
        //2.判断关键参数
        verifyCourseMsg(courseDto);

        //3.根据课程id查询课程是否存在
        Long id = courseDto.getCourseBaseId();
        if (ObjectUtils.isEmpty(id)) {
            throw new RuntimeException("缺少参数");
        }
        CourseBaseDTO resoultDto = queryByCourseID(id, courseDto.getCompanyId());
        if (ObjectUtils.isEmpty(resoultDto)) {
            throw new RuntimeException("课程不存在");
        }
        //4.判断课程状态，只有未提交或者审核未通过的才能修改
        String status = resoultDto.getAuditStatus();
        if (!CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(status) &&
                !CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(status)
        ) {
            throw new RuntimeException("课程已提交不能修改");
        }
        //5.判读是否是同一家机构
        if (!ObjectUtils.nullSafeEquals(courseDto.getCompanyId(), resoultDto.getCompanyId())) {
            throw new RuntimeException("权限不足修改失败");
        }

        //6.修改数据，
        //6.1 dtp-->po,修改课程基本信息数据
        CourseBase courseBase = CourseConvert.INSTANCE.DTO2entity(courseDto);
        boolean update = this.updateById(courseBase);

        if (!update) {
            throw new RuntimeException("修改课程基本信息数据失败");
        }

        //6.2修改营销数据
        LambdaUpdateWrapper<CourseMarket> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseMarket::getCharge, courseDto.getCharge());
        updateWrapper.set(CourseMarket::getPrice, courseDto.getPrice());
        updateWrapper.eq(CourseMarket::getCourseId, courseBase.getId());

        boolean update1 = courseMarketService.update(updateWrapper);
        if (!update1) {
            throw new RuntimeException("修改营销数据失败");
        }
        //7.封装数据进行返回
        return courseDto;
    }

    /*
        删除课程信息分析
        1.是否要添加事务
        2.判断关键参数
        3.查询数据是否为已删除状态
        4.判断数据是否是未提交和审核失败
        5.判断是否是同一个机构
        6.判断是否营销数据
        7.修改数据状态为已删除
        8.返回结果，
     */
    @Override
    @Transactional // 1.添加事务
    public Boolean deleteCourseBase(Long courseId, Long companyId) {
        //2.判断关键参数
        if(ObjectUtils.isEmpty(courseId) || ObjectUtils.isEmpty(companyId)){
            //只要有一个为空就不行
            throw new RuntimeException("缺少关键参数");
        }
        //3.查询数据是否为已删除状态
        CourseBaseDTO dto = queryByCourseID(courseId, companyId);
        if(ObjectUtils.isEmpty(dto)){
            throw new RuntimeException("课程信息不存在");
        }
        //4.判断课程状态，只有未提交或者审核未通过的才能操作
        String status = dto.getAuditStatus();
        if (!CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(status) &&
                !CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(status)
        ) {
            throw new RuntimeException("课程已提交不能修改");
        }
        //5.判读是否是同一家机构
        if (!ObjectUtils.nullSafeEquals(dto.getCompanyId(), dto.getCompanyId())) {
            throw new RuntimeException("权限不足修改失败");
        }
        //6.判断是否营销数据
        LambdaQueryWrapper<CourseMarket> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseMarket::getCourseId, courseId);
        CourseMarket courseMarket = courseMarketService.getOne(wrapper);
        //6.1判断营销数据是否存在
        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("营销数据不存在");
        }
        //7.修改数据状态为已删除
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();

        updateWrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG.getCode());
        updateWrapper.eq(CourseBase::getId,courseId);

        boolean boo = this.update(updateWrapper);
        //8.返回结果，
        return boo;
    }


    /*
         提交课程业务分析
         1.判断关键数据
         2.判断课程是否存在
         3.判断课程是否被删除
         4.判断是否同一家机构
         5.判断审核状态（只有未提交、审核失败才能操作）
         6.修改状态未已提交
         7.判断修改结果
     */
    @Transactional
    public void commitCourseBase(Long courseBaseId, Long companyId) {
        //1.判断关键数据
        if(ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(companyId)){
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }
        //2.判断课程是否存在
        CourseBase courseBase = this.getById(courseBaseId);
        if(ObjectUtils.isEmpty(courseBase)){
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }

        //3.判断课程是否被删除
        if(!(ObjectUtils.nullSafeEquals(CommonEnum.USING_FLAG.getCodeInt(),courseBase.getStatus()))){
            //不是使用状态的都报错
            ExceptionCast.cast(ContentErrorCode.E_120019);
        }
        //4.判断是否同一家机构
        if(!(ObjectUtils.nullSafeEquals(companyId,courseBase.getCompanyId()))){
            ExceptionCast.cast(ContentErrorCode.E_120020);
        }
        //5.判断审核状态（只有未提交、审核失败才能操作）
        String status = courseBase.getAuditStatus();
        if (!CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(status) &&
                !CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode().equals(status)
        ) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        //6.修改状态为已提交

        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus,CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode() );
        updateWrapper.eq(CourseBase::getId,courseBaseId);
        boolean update = this.update(updateWrapper);
        //7.判断修改结果
        if(!update){
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }


    }

    /*
        审核课程信息分析：
        1.判断关键数据
                auditStatus，courseBaseId

        2.判断传入的审核状态（只能审核通过或审核不通过才能操作）
        3.判断课程是否存在
        4.判断课程是否被删除
        5.判断查询出来的数据是否是提交状态
        6.修改状态未传入的状态。通过或者不通过
        7.判断修改结果

     */
    public void approveCourse(CourseBaseDTO dto) {
        String status = dto.getAuditStatus();
        Long courseBaseId = dto.getCourseBaseId();
        //1.判断关键数据
        //auditStatus，courseBaseId
        if(ObjectUtils.isEmpty(status) ||
                ObjectUtils.isEmpty(courseBaseId)){
            ExceptionCast.cast(ContentErrorCode.E_120018);

        }
        //2.判断传入的审核状态（只能审核通过或审核不通过才能操作）
        if(!(CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode().equals(status)) &&
                !(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(status))
        ){
            ExceptionCast.cast(ContentErrorCode.E_120016);

        }
        //3.判断课程是否存在
        CourseBase courseBase = this.getById(courseBaseId);
        if(ObjectUtils.isEmpty(courseBase)){
            ExceptionCast.cast(ContentErrorCode.E_120013);

        }
        //4.判断课程是否被删除
        if(CommonEnum.DELETE_FLAG.getCodeInt().equals(courseBase.getStatus())){
            ExceptionCast.cast(ContentErrorCode.E_120019);
        }
        //5.判断查询出来的数据是否是提交状态

        if(!(CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(courseBase.getAuditStatus()))){
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        //6.修改状态未传入的状态。通过或者不通过
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getAuditStatus,status);
        updateWrapper.set(CourseBase::getAuditMind,dto.getAuditMind());

        updateWrapper.eq(CourseBase::getId,courseBaseId);

        boolean update = this.update(updateWrapper);

        //7.判断修改结果
        if(!update){
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }

    }

    /**
     * 封装对DTO的关键数据判断
     *
     * @param dto 传入的DTO
     */
    public void verifyCourseMsg(CourseBaseDTO dto) {
        if (!(StringUtil.isBlank(dto.getCharge())) &&
                !(StringUtil.isBlank(dto.getGrade())) &&
                !(StringUtil.isBlank(dto.getMt())) &&
                !(StringUtil.isBlank(dto.getName())) &&
                !(StringUtil.isBlank(dto.getSt())) &&
                !(StringUtil.isBlank(dto.getTeachmode())) &&
                !(StringUtil.isBlank(dto.getUsers())) &&
                !(ObjectUtils.isEmpty(dto.getCompanyId()))
        ) {
            return;
        }

        throw new RuntimeException("缺少参数");
    }
}
